home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / dkbtrace / pbmplus / source / ppm / ppmtopcx.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-06  |  8.9 KB  |  383 lines

  1. /* ppmtopcx.c - read a portable pixmap and produce a PCX file
  2. **
  3. ** Copyright (C) 1990 by Michael Davidson.
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. */
  12.  
  13. #include <stdio.h>
  14. #include "ppm.h"
  15. #include "ppmcmap.h"
  16.  
  17. #define MAXCOLORS    256
  18. #define    MAXPLANES    4
  19.  
  20. /*
  21.  * Pointer to function returning an int
  22.  */
  23. typedef void (* vfunptr) ARGS(( int, int, unsigned char*, int, int ));
  24.  
  25. static void PCXEncode ARGS(( FILE* fp, int GWidth, int GHeight, int Colors, int Red[], int Green[], int Blue[], vfunptr GetPlanes ));
  26. static void PutPlane ARGS(( FILE* fp, unsigned char* buf, int Size ));
  27. static void ReadPlanes ARGS(( int y, int width, unsigned char* buf, int planes, int bits ));
  28. static void Putword ARGS(( int w, FILE* fp ));
  29. static void Putbyte ARGS(( int b, FILE* fp ));
  30.  
  31. static pixel** pixels;
  32. static colorhash_table cht;
  33.  
  34. void
  35. main( argc, argv )
  36.     int argc;
  37.     char* argv[];
  38.     {
  39.     FILE* ifp;
  40.     int argn, rows, cols, colors, i;
  41.     pixval maxval;
  42.     pixel black_pixel;
  43.     colorhist_vector chv;
  44.     int Red[MAXCOLORS], Green[MAXCOLORS], Blue[MAXCOLORS];
  45.     char* usage = "[ppmfile]";
  46.  
  47.     ppm_init( &argc, argv );
  48.  
  49.     argn = 1;
  50.  
  51.     if ( argn < argc )
  52.     {
  53.     ifp = pm_openr( argv[argn] );
  54.     ++argn;
  55.     }
  56.     else
  57.     ifp = stdin;
  58.  
  59.     if ( argn != argc )
  60.     pm_usage( usage );
  61.  
  62.     pixels = ppm_readppm( ifp, &cols, &rows, &maxval );
  63.  
  64.     pm_close( ifp );
  65.  
  66.     /* Figure out the colormap. */
  67.     pm_message( "computing colormap..." );
  68.     chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &colors );
  69.     if ( chv == (colorhist_vector) 0 )
  70.     pm_error(
  71.         "too many colors - try doing a 'ppmquant %d'", MAXCOLORS );
  72.     pm_message( "%d colors found", colors );
  73.  
  74.     /* Force black to slot 0 if possible. */
  75.     PPM_ASSIGN(black_pixel, 0, 0, 0 );
  76.     ppm_addtocolorhist(chv, &colors, MAXCOLORS, &black_pixel, 0, 0 );
  77.  
  78.     /* Now turn the ppm colormap into the appropriate PCX colormap. */
  79.     if ( maxval > 255 )
  80.     pm_message(
  81.         "maxval is not 255 - automatically rescaling colors" );
  82.     for ( i = 0; i < colors; ++i )
  83.     {
  84.     if ( maxval == 255 )
  85.         {
  86.         Red[i] = PPM_GETR( chv[i].color );
  87.         Green[i] = PPM_GETG( chv[i].color );
  88.         Blue[i] = PPM_GETB( chv[i].color );
  89.         }
  90.     else
  91.         {
  92.         Red[i] = (int) PPM_GETR( chv[i].color ) * 255 / maxval;
  93.         Green[i] = (int) PPM_GETG( chv[i].color ) * 255 / maxval;
  94.         Blue[i] = (int) PPM_GETB( chv[i].color ) * 255 / maxval;
  95.         }
  96.     }
  97.  
  98.     /* And make a hash table for fast lookup. */
  99.     cht = ppm_colorhisttocolorhash( chv, colors );
  100.     ppm_freecolorhist( chv );
  101.  
  102.     /* All set, let's do it. */
  103.     PCXEncode( stdout, cols, rows, colors, Red, Green, Blue, ReadPlanes );
  104.  
  105.     pm_close (stdout);
  106.  
  107.     exit( 0 );
  108.     }
  109.  
  110. /*****************************************************************************
  111.  *
  112.  * PCXENCODE.C    - PCX Image compression interface
  113.  *
  114.  * PCXEncode( FName, GHeight, GWidth, Colors, Red, Green, Blue, GetPlanes )
  115.  *
  116.  *****************************************************************************/
  117.  
  118. #define TRUE 1
  119. #define FALSE 0
  120.  
  121. /* public */
  122.  
  123. static void
  124. PCXEncode(fp, GWidth, GHeight, Colors, Red, Green, Blue, GetPlanes )
  125. FILE* fp;
  126. int GWidth, GHeight;
  127. int Colors;
  128. int Red[], Green[], Blue[];
  129. vfunptr GetPlanes;
  130. {
  131.     int        BytesPerLine;
  132.     int        Planes;
  133.     int        BitsPerPixel;
  134.     unsigned char    *buf;
  135.     int        i;
  136.     int        n;
  137.     int        y;
  138.  
  139.     /*
  140.      * select number of planes and number of bits
  141.      * per pixel according to number of colors
  142.      */
  143.     /*
  144.      * 16 colors or less are handled as 1 bit per pixel
  145.      * with 1, 2, 3 or 4 color planes.
  146.      * more than 16 colors are handled as 8 bits per pixel
  147.      * with 1 plane
  148.      */
  149.     if (Colors > 16)
  150.     {
  151.         BitsPerPixel    = 8;
  152.         Planes        = 1;
  153.     }
  154.     else
  155.     {
  156.         BitsPerPixel    = 1;
  157.         if (Colors > 8)
  158.             Planes = 4;
  159.         else if (Colors > 4)
  160.             Planes = 3;
  161.         else if (Colors > 2)
  162.             Planes = 2;
  163.         else
  164.             Planes = 1;
  165.     }
  166.  
  167.         /*
  168.          * Write the PCX header
  169.          */
  170.     Putbyte( 0x0a, fp);        /* .PCX magic number        */
  171.     Putbyte( 0x05, fp);        /* PC Paintbrush version    */
  172.     Putbyte( 0x01, fp);        /* .PCX run length encoding    */
  173.     Putbyte( BitsPerPixel, fp);    /* bits per pixel        */
  174.  
  175.         Putword( 0, fp );        /* x1    - image left        */
  176.         Putword( 0, fp );        /* y1    - image top        */
  177.     Putword( GWidth-1, fp );    /* x2    - image right        */
  178.     Putword( GHeight-1, fp );    /* y2    - image bottom        */
  179.  
  180.     Putword( GWidth, fp );        /* horizontal resolution    */
  181.     Putword( GHeight, fp );        /* vertical resolution        */
  182.  
  183.         /*
  184.          * Write out the Color Map for images with 16 colors or less
  185.          */
  186.     n = (Colors <= 16) ? Colors : 16;
  187.         for (i = 0; i < n; ++i)
  188.     {
  189.                 Putbyte( Red[i], fp );
  190.                 Putbyte( Green[i], fp );
  191.                 Putbyte( Blue[i], fp );
  192.         }
  193.         for (; i < 16; ++i)
  194.     {
  195.                 Putbyte( 255, fp );
  196.                 Putbyte( 255, fp );
  197.                 Putbyte( 255, fp );
  198.         }
  199.  
  200.     Putbyte( 0, fp);        /* reserved byte        */
  201.  
  202.     Putbyte( Planes, fp);        /* number of color planes    */
  203.  
  204.     BytesPerLine    = ((GWidth * BitsPerPixel) + 7) / 8;
  205.     Putword( BytesPerLine, fp );    /* number of bytes per scanline    */
  206.  
  207.     Putword( 1, fp);        /* pallette info        */
  208.  
  209.     for (i = 0; i < 58; ++i)    /* fill to end of header    */
  210.         Putbyte( 0, fp );
  211.  
  212.     buf    = (unsigned char *)malloc( MAXPLANES * BytesPerLine );
  213.  
  214.     for (y = 0; y < GHeight; ++y)
  215.     {
  216.         (*GetPlanes)(y, GWidth, buf, Planes, BitsPerPixel);
  217.  
  218.         for (i = 0; i < Planes; ++i)
  219.             PutPlane(fp, buf + (i * BytesPerLine), BytesPerLine);
  220.     }
  221.  
  222.     /*
  223.      * color map for > 16 colors is at end of file
  224.      */
  225.     if (Colors > 16)
  226.     {
  227.         Putbyte( 0x0c, fp);        /* magic for 256 colors */
  228.             for (i = 0; i < Colors; ++i)
  229.         {
  230.                     Putbyte( Red[i], fp );
  231.                     Putbyte( Green[i], fp );
  232.                     Putbyte( Blue[i], fp );
  233.             }
  234.             for (; i < MAXCOLORS; ++i)
  235.         {
  236.                     Putbyte( 255, fp );
  237.                     Putbyte( 255, fp );
  238.                     Putbyte( 255, fp );
  239.             }
  240.     }
  241.  
  242.         fclose( fp );
  243. }
  244.  
  245. static void
  246. PutPlane(fp, buf, Size)
  247. FILE        *fp;
  248. unsigned char    *buf;
  249. int        Size;
  250. {
  251.     unsigned char    *end;
  252.     int        c;
  253.     int        previous;
  254.     int        count;
  255.  
  256.     end    = buf + Size;
  257.  
  258.     previous = *buf++;
  259.     count     = 1;
  260.  
  261.     while (buf < end)
  262.     {
  263.         c = *buf++;
  264.         if (c == previous && count < 63)
  265.         {
  266.             ++count;
  267.             continue;
  268.         }
  269.  
  270.         if (count > 1 || (previous & 0xc0) == 0xc0)
  271.         {
  272.             count |= 0xc0;
  273.             Putbyte ( count , fp );
  274.         }
  275.         Putbyte(previous, fp);
  276.         previous = c;
  277.         count    = 1;
  278.     }
  279.  
  280.     if (count > 1 || (previous & 0xc0) == 0xc0)
  281.     {
  282.         count |= 0xc0;
  283.         Putbyte ( count , fp );
  284.     }
  285.     Putbyte(previous, fp);
  286. }
  287.  
  288. static unsigned long PixMap[8][16] =
  289. {
  290.     0x00000000L,    0x00000080L,    0x00008000L,    0x00008080L,
  291.     0x00800000L,    0x00800080L,    0x00808000L,    0x00808080L,
  292.     0x80000000L,    0x80000080L,    0x80008000L,    0x80008080L,
  293.     0x80800000L,    0x80800080L,    0x80808000L,    0x80808080L,
  294. };
  295.  
  296. static void
  297. ReadPlanes(y, width, buf, planes, bits)
  298. int        y;
  299. int        width;
  300. unsigned char    *buf;
  301. int        planes;
  302. int        bits;
  303. {
  304.     static int    first_time = 1;
  305.     unsigned char    *plane0, *plane1, *plane2, *plane3;
  306.     int        i, j, x;
  307.  
  308.     /*
  309.      * 256 color, 1 plane, 8 bits per pixel
  310.      */
  311.     if (planes == 1 && bits == 8)
  312.     {
  313.         for (x = 0; x < width; ++x)
  314.             buf[x] = ppm_lookupcolor( cht, &pixels[y][x] );
  315.         return;
  316.     }
  317.  
  318.     /*
  319.      * must be 16 colors or less, 4 planes or less, 1 bit per pixel
  320.      */
  321.     if (first_time)
  322.     {
  323.         for (i = 1; i < 8; ++i)
  324.             for (j = 0; j < 16; ++j)
  325.                 PixMap[i][j] = PixMap[0][j] >> i;
  326.         first_time = 0;
  327.     }
  328.  
  329.     i = (width + 7) / 8;
  330.  
  331.     plane0    = buf;
  332.     plane1    = plane0 + i;
  333.     plane2    = plane1 + i;
  334.     plane3    = plane2 + i;
  335.  
  336.     i    = 0;
  337.     x    = 0;
  338.  
  339.     while ( x < width )
  340.     {
  341.         register unsigned long    t;
  342.  
  343.         t     = PixMap[0][ppm_lookupcolor( cht, &pixels[y][x++] )];
  344.         t    |= PixMap[1][ppm_lookupcolor( cht, &pixels[y][x++] )];
  345.         t    |= PixMap[2][ppm_lookupcolor( cht, &pixels[y][x++] )];
  346.         t    |= PixMap[3][ppm_lookupcolor( cht, &pixels[y][x++] )];
  347.         t    |= PixMap[4][ppm_lookupcolor( cht, &pixels[y][x++] )];
  348.         t    |= PixMap[5][ppm_lookupcolor( cht, &pixels[y][x++] )];
  349.         t    |= PixMap[6][ppm_lookupcolor( cht, &pixels[y][x++] )];
  350.         t    |= PixMap[7][ppm_lookupcolor( cht, &pixels[y][x++] )];
  351.  
  352.         plane0[i] = t;
  353.         plane1[i] = t >> 8;
  354.         plane2[i] = t >> 16;
  355.         plane3[i++] = t >> 24;
  356.     }
  357. }
  358.  
  359. /*
  360.  * Write out a word to the PCX file
  361.  */
  362. static void
  363. Putword( w, fp )
  364. int w;
  365. FILE *fp;
  366. {
  367.         fputc( w & 0xff, fp );
  368.         fputc( (w / 256) & 0xff, fp );
  369. }
  370.  
  371. /*
  372.  * Write out a byte to the PCX file
  373.  */
  374. static void
  375. Putbyte( b, fp )
  376. int b;
  377. FILE *fp;
  378. {
  379.         fputc( b & 0xff, fp );
  380. }
  381.  
  382. /* The End */
  383.